package net.gdface.service.search;

import java.net.MalformedURLException;
import java.net.URI;
import java.util.concurrent.TimeUnit;

import net.gdface.httpclient.AsyncClientManager;
import net.gdface.httpclient.HostManager;
import net.gdface.service.client.FetchImage;
import net.gdface.service.client.WorkDataJSON;
import net.gdface.utils.Assert;
import net.gdface.worker.NoTimeupException;
import net.gdface.worker.QueueManager;
import net.gdface.worker.WorkData;

import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 图像下载线程
 * @author guyadong
 *
 */
public class DownloadWorker implements Runnable {
	private static final Logger logger = LoggerFactory.getLogger(DownloadWorker.class);
	private static QueueManager<RemoteImageWOC> queueManager;
	private static long timeoutMills = 2000;
	private static double safeThreshold=0.75;
	private static FetchImage saveProcessor;
	public static void set(QueueManager<RemoteImageWOC> queueManager, FetchImage saveProcesser, long timeoutMills, double safeThreshold) {
		Assert.notNull(queueManager, "queueManager");
		Assert.notNull(saveProcesser, "saveProcesser");
		DownloadWorker.queueManager = queueManager;
		DownloadWorker.saveProcessor=saveProcesser;
		if (timeoutMills > 0)
			DownloadWorker.timeoutMills = timeoutMills;
		if(safeThreshold>0.0&&safeThreshold<=1.0){
			DownloadWorker.safeThreshold=safeThreshold;
		}
	}
	public DownloadWorker() {
	}

	@Override
	public void run() {
		RemoteImageWOC woc=null;
		try {
			//从队列中取出数据，超时结束
			//当前工作任务如果超过asyncClient连接池的最大连接数，会造成阻塞，抛出ConnectionPoolTimeoutException,
			//连接过多也会导致网络变慢，Timeout机率更高，所以在这里限制WOKING_DATA的大小，超过安全限额就不再产生更多的网络请求
			//WOKING_DATA的安全限额设置为ASYNC_CLIENT_MAX_CONNECTIONS的safeThreshold倍时休眠
			while (true) {				
				while(WorkData.WOKING_DATA.size() >= (int)(AsyncClientManager.getInstance().getMaxConnection()*safeThreshold)){
					//logger.info("WOKING_DATA FULL sleep {} mills zzZ",timeoutMills);
					System.out.print("zzZ...");
					Thread.sleep(timeoutMills);
				}					
				if(null != (woc = queueManager.pop(timeoutMills, TimeUnit.MILLISECONDS)))
					submit(woc);
				else
					break;
			}
		} catch (RuntimeException e) {
			logger.error(e.getMessage(), e);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}
	
	
	public void submit(RemoteImageWOC woc) throws InterruptedException{
		Assert.notNull(woc, "woc");
		JSONObject jo=null;
		URI imgUri=null;
		try {
			//过滤掉空的json对象
			if (null != (jo=woc.getJson()) && 0 != jo.length()) {
				//因为json对象中可能包含新加入的重试信息ImgJsonDecoder.KEY_RETRY字段，所以需要更新
				//所以在这里不区分是否是重试的任务，重新用ImgJsonDecoder解码器解析生成新的ImgInfo对象
				//并更新局部变量VAR_IMGINFO
				ImgInfo imginfo=ImgJsonDecoderManager.getJsonDecoder(jo).create(jo);				
				woc.setVariables(WorkDataJSON.VAR_IMGINFO, imginfo);				
				imgUri = imginfo.getLocaction();
				//如果不是绝对地址，则放弃
				//在此把关,把所有不合格的地址过滤掉
				if (!imgUri.toString().isEmpty()&&imgUri.isAbsolute()) {
					saveProcessor.fetchAsyncThrowIfNoTimeup(woc);
				}/*else
					logger.info("Not isAbsolute URI [{}]",imgUri.toString());*/
			}
		} catch (JSONException e) {
			logger.warn("{}\n{}",e.toString(),jo);
		} catch (MalformedURLException e) {
			logger.warn("{}\n{}",e.toString(),jo);
		}catch (NoTimeupException e) {
			// 显式捕获NoTimeup异常，间隔未到的任务对象重新放回队列,延期执行
			long gap=e.getGapMills()>0?e.getGapMills():HostManager.DEFAULT_INTERVAL_MILLS;			
			queueManager.push(woc, gap);
			//logger.info("{} [{}] {}",e.getClass().getSimpleName(),times,woc.getURI());
		}finally{
		}

	}
}

